Projet Zuul de conception orientée objet en Java d'un jeu d'aventure
Forum des exercices du projet Zuul
Exercice 7.46.1
Pour pouvoir continuer à tester le jeu grâce aux séquences de tests (voir exercices 7.27 à 7.28.3), et compte tenu du caractère aléatoire du mécanisme de transporter room, il devient nécessaire (pour qu'un fichier de test puisse s'exécuter sans
problème jusqu'à gagner le jeu, même s'il passe par la transporter room) d'inventer une nouvelle commande : alea.
- alea string : mémorise la string pour pouvoir déterminer le résultat du prochain tirage "aléatoire" (quand on sortira de la transporter room),
- alea : vide la string pour permettre au prochain tirage d'être réellement aléatoire.
Cette commande ne doit pouvoir être utilisée qu'en mode test (c'est-à-dire pendant l'exécution d'un fichier de test), sauf peut-être pendant les phases de mise au point du programme.
Ne pas oublier de lire les échanges ci-dessous pour mieux comprendre la bonne manière de réaliser cet exercice.
"- alea string : mémorise la string pour pouvoir déterminer le résultat du prochain tirage "aléatoire"
- alea : vide la string pour permettre au prochain tirage d'être réellement aléatoire"
Je ne vois pas de quel string vous parlez, pouvez-vous expliquer?
Cordialement.
Si on imagine que vous tapez alea cuisine, puis que vous passez par la TransporterRoom, vous êtes sûr d'être transporté dans la cuisine.
"cuisine" est ici la String qu'il faut mémoriser.
Doit-on créer une HashMap<String, Room> pour récupérer la Room par la String, obtenue à partir du second mot tapé à la suite de "alea"?
Pourquoi pas ?
Mais cela dépend de la façon dont vous avez programmé l'exercice 7.46.
L'étudiant a répondu :
Alors le plus simple est peut-être d'utiliser une commande 'alea 3' par exemple, si voulez retenir la 4ème pièce de votre tableau.
Si vous voulez pouvoir écrire 'alea Cuisine', il faudra rechercher dans le tableau quelle pièce porte ce nom-là. Créer une HashMap juste pour être utilisée une seule fois (dans la commande alea) est peut-être un peu coûteux, mais ce n'est pas interdit.
J'ai implémenté la commande alea ainsi que attribut String aAlea pour contenir le nom de la salle dans laquelle la TransporterRoom va amener. J'ai aussi créé le getter de cette variable.
Mais je ne sais pas comment donner accès à cette variable à TransporterRoom. J'avais pensé à créer un attribut GameEngine dans TransporterRoom, mais la variable aAlea n'est pas appelée sur cet attribut (elle est appelée sur le GameEngine créé par Game). Donc TransporterRoom n'aura jamais la bonne valeur de aAlea de cette manière.
Merci d'avance pour votre aide.
Suite à un pb technique, je viens seulement d'être prévenu de votre message.
Vous ne dites pas où vous avez mis l'attribut aAlea, mais j'ai l'impression que vous avez pris le pb à l'envers.
Il vaut mieux que ce soit la TransporterRoom qui mémorise la pièce qu'elle devra fournir à chaque appel de getExit(). Il faut juste prévoir un setter pour la lui préciser lorsque la commande alea est exécutée.
Bonjour,
J'ai réfléchi a plusieurs architectures pour coder cette commande et la meilleure façon (du moins la plus économe) me semble celle ci :
Ajouter une procédure alea(final Command pCommand) dans TransporterRoom qui mettra un attribut de la classe de type String soit en null si pas de SecondWord ou bien en string de la room que l'on veut. Puis dans getRandomRoom, si cette string == null, on change rien, si != null alors on renvoie la Room qu'il faut.
Est ce correct a ce que l'on doit faire ?
Si oui, j'ai un problème pour la mettre en place. Toute les méthodes que l'on appelle dans notre jeu sont dans GameEngine ou Player. On crée une TransporterRoom dans CreateRoom() mais en variable temporaire non en attribut on ne peut donc pas appeler cette méthode..
Et aucun accesseur est possible..
Faut-il alors créer cette méthode alea dans Player ou bien GameEngine ?
(Sinon j'ai pensé a l'écrire dans Player, caster aCurrentRoom en TransporterRoom si .getClass().getName() == "TransporterRoom" et faire ce qu'il faut mais ca fait beaucoup d'accesseur a écrire et cette façon de faire ne me plait guère..)
Ce qu'il faut faire c'est ajouter deux attributs dans le GameEngine, une Room qu'on va appeler roomTestMode par exemple et un booleen qu'on va appeler testMode et qui sert à savoir si on est en mode debug (en mode test quoi).
Quand le jeu reçoit la commande "alea cuisine", ça enregistre la Room cuisine dans la variable roomTestMode. Pour retrouver la Room depuis une String, il faut avoir fait l'exercice facultatif au début du jeu qui proposait d'enregistrer toutes les Room créées dans le GameEngine dans une HashMap<String, Room> (prévoit un cas d'erreur si jamais le mec tape nimp genre alea drjbrjhbszef). Et quand le jeu reçoit la commande "alea" bah tu mets la roomTestMode à null.
Ensuite t'as plus qu'à modifier la méthode goRoom et ajouter un cas, si le jeu est en mode de test (donc testMode vaut true) et que le mec est dans une transporterRoom, alors la prochaine room = roomTestMode.
Ah et vérifie bien que la commande aléa n'est utilisable que en mode test, faut pas que le mec puisse écrire aléa, seulement le fichier de test peut utiliser cette commande.
Et je crois que c'est à peu près tout !
PS : On n'écrit pas getClass().getName() == "TransporterRoom" mais tonObjetTransporterRoom instanceof TransporterRoom.
Une autre (meilleure ?) solution est de mémoriser la aleaString dans TransporterRoom assortie d'un setter.
getExit() retournerait systématiquement la Room qui porte le nom aleaString quand elle ne vaut pas null ; dans le cas contraire, getExit() retournerait le résultat fourni par RoomRandomizer.
Pour le reste, il faut effectivement gérer un booléen testMode dans GameEngine
pour n'effectuer la commande alea que lorsqu'on est en mode test, c'est-à-dire en lecture des commandes à partir d'un fichier.
Bonjour Monsieur,
Ça fait déjà pas mal de temps que je suis bloqué sur cet exercice. Je n'arrive pas à programmer la chose. J'ai bien compris qu'on ne devait utiliser la commande "alea" qu'en mode test. Cependant, je vois pas comment faire. Car si on mettrait un boolean à true lorsque que test est appelé comment faire la même chose pour dire que la commande alea est utilisé lorsque cette variable vaut true ? Il ne faut pas la mettre parmi tous les CASE non ?
Ma seconde interrogation est comment obtenir une Room à partir de sa string. Je ne comprends pas votre dernière réponse. Vous dites qu'il faut mémoriser aleaString dans TransporteurRoom mais l'aleaString peut correspondre à une Room et n'est pas forcément une TransporTeurRoom (j'ai peut-être mal compris l'exercice?). Même si j'arrive à enregistrer la Room à partir de sa String, je ne vois pas comment faire en sorte pour que la sortie de la TransporteurRoom soit la Room de mon aleaString.
Cordialement
Bonjour, et bonne année 2016 !
1) La commande alea figurera comme les autres dans le switch, mais elle commencera par tester le booléen estEnModeTest et se terminera sans rien faire si celui-ci vaut false.
2) aleaString est le nom de la pièce dans laquelle on veut être transporté en sortant de la TransporterRoom. Si vous disposez d'une HashMap qui associe chaque Room à son nom, votre problème est résolu ! (voir exercice 7.18.5)
Bonjour M. BUREAU,
il y a quelque chose que je ne comprend pas dans cet exercice c'est comment accéder à la TransporterRoom pour lui changer sa valeur AleaString dans GameEngine ?
En effet dans mon cas elle est définit dans la méthode createRooms() de la classe GameModel.
Faudrait-il
que je créer un attribut avec un getter juste pour définir
cette TransporterRoom ? Cependant dans ce cas cela serais une
mauvaise façon de programmer selon moi si il existe
plusieurs TransporterRoom.
Ou alors faut-il que AleaString
soit static ? Mais dans ce cas on ne pourrait pas faire de traitement
individuel si il y a plusieurs TransporterRoom.
Je ne vois pas pourquoi la solution décrite ci-dessus (mercredi 23 décembre 2015) ne convient pas.
C'est la solution que je tente d'implémenter.
Cependant je ne vois pas à quel moment utiliser le setter.
Certes nous pouvons créer un attribut TransporterRoom dans GameModel ( ou GameEngine selon si on a fait une architecture MVC ou pas ) mais cela ne serais pas propre si on doit le faire pour plusieurs TransporterRoom non ?
Le setter doit être utilisé dans la commande alea.
Pour avoir accès à la TransporterRoom,
une solution est de la chercher dans la collection de l'exercice 7.18.5 :
si c'est une HashMap, par son nom, si c'est une liste, par son numéro.
Un étudiant a écrit :
Dans l'exercice alea, j'ai reussi a faire la commande qui fonctionne mais la Room a renvoyer est stocké dans la classe RoomRandomizer et non dans TransporterRoom comme vous l'avez dit dans les commentaires de cet exercice, je ne sais pas si c'est dérangeant.
C'est "dérangeant" car il n'est pas logique de "déranger" le RoomRandomizer
alors qu'on ne veut pas faire de tirage au sort.
Il ne doit pas être bien difficile de déplacer l'attribut de RoomRandomizer
vers TransporterRoom ...
Réseaux sociaux